import business.*
import enums.Direction
import enums.EnhanceType
import ext.checkCollision
import javafx.scene.input.KeyCode
import javafx.scene.input.KeyEvent
import model.*
import org.itheima.kotlin.game.core.Composer
import org.itheima.kotlin.game.core.Window
import java.io.File
import java.util.*
import java.util.concurrent.CopyOnWriteArrayList

class GameWindow :Window(title =GameConfig.title,width = GameConfig.WINDOW_WIDTH,
    height=GameConfig.WINDOW_HEIGHT,icon = GameConfig.icon) {

    /** 所有元素的集合 */
    var views=CopyOnWriteArrayList<IView>()

    /** lateinit 使用时在创建，可以不再这里初始化*/
    lateinit var mTank:MyTank/** lateinit 使用时在创建，可以不再这里初始化*/
    var isShowGameOver=false//是否已显示

    var gameOver=false //游戏是否结束
    var startTimerTime=0L //敌方坦克定时开始时间
    var timerLength=1000*5 //定时时长

    var activeEnemyNum=0  //活跃的敌方坦克数量
    var totalEnemyNum=20  //敌方坦克的总数
    var bornEnemyNum=0 //已出生的敌方坦克数量
    val maxActiveEnemyTank=3  //敌方坦克的最大活跃数量
    val checkTimeSpace=1200  //检测敌方坦克活跃数的时间间隔
    var lastCheckTime=0L  //最后一次检测敌方坦克的时间

    var activeMyTankNum=0  //活跃的我方坦克数量
    var totalMyTankNum=3  //我方坦克的总数
    var bornMyTankNum=0 //已出生的我方坦克数量

    override fun onCreate() {
//        println("窗体创建了")

        var map=File(javaClass.getResource("/map/4.map").path)
        var lines=map.readLines()
        var lineNum=0

        /** 双重for循环遍历每一个子*/
        lines.forEach{line->
            var columnNum=0
            line.toCharArray().forEach { column->

//                println("columnNum="+columnNum+"  lineNum="+lineNum)
                when(column){
                    '砖'-> views.add(Wall(GameConfig.SMALL_BLOCK_WIDTH*columnNum,GameConfig.SMALL_BLOCK_WIDTH*lineNum))
                    '水'-> views.add(Water(GameConfig.SMALL_BLOCK_WIDTH*columnNum,GameConfig.SMALL_BLOCK_WIDTH*lineNum))
                    '铁'-> views.add(Steel(GameConfig.SMALL_BLOCK_WIDTH*columnNum,GameConfig.SMALL_BLOCK_WIDTH*lineNum))
                    '草'-> views.add(Grass(GameConfig.SMALL_BLOCK_WIDTH*columnNum,GameConfig.SMALL_BLOCK_WIDTH*lineNum))
                }
                columnNum++
            }
            lineNum++
        }

        views.addAll(Camp().create())
//        println("views.size="+views.size)

        Composer.play("snd/start.wav")
    }

    override fun onDisplay() {
        //窗体绘制
        views.forEach{
            it.draw()
        }

//        println("views.size="+views.size)
    }

    override fun onKeyPressed(event: KeyEvent) {
        //按键监听
        when(event.code){
            KeyCode.UP-> mTank.move(Direction.UP)
            KeyCode.DOWN-> mTank.move(Direction.DOWN)
            KeyCode.LEFT-> mTank.move(Direction.LEFT)
            KeyCode.RIGHT-> mTank.move(Direction.RIGHT)
            KeyCode.SPACE->{
                var bullet=mTank.shot() //发射子弹
                bullet?.let {
                    views.add(bullet)
                }
            }
        }
    }

    var lastTime=0L
    override fun onRefresh() {
        var currentTime=System.currentTimeMillis()
//        println("time-lastTime=="+(time-lastTime))
        lastTime=currentTime

        /** 检测自动移动 */
        views.filter { it is AutoMoveable}.forEach {autoMove->
            autoMove as AutoMoveable
            if(gameOver){
                if((autoMove is GameOverText) or (autoMove is Bullet))
                    autoMove.move(autoMove.currentDirection)
            }else{
                if(( autoMove is EnemyTank)and (currentTime-startTimerTime< timerLength)){
                }else{
                    autoMove.move(autoMove.currentDirection)
                }
            }
        }

        /** 如果游戏已经结束，后面的逻辑不执行*/
        if((gameOver)and (!isShowGameOver)){
            views.add(GameOverText())
            isShowGameOver=true
        }

        /** 碰撞检测*/
        views.filter { it is Moveable }.forEach { move->
            move as Moveable

            var badDirection:Direction?=null
            var blockable:Blockable?=null

            views.filter { (it is Blockable) and (it!=move)}.forEach blockTag@{ block->
                block as Blockable
                //判断这一个运动的物体和这一个阻塞物体是否会发送碰撞
                var direction=move.willCollision(block)
                //当badDirection 不等于null，说明运动物体会和这个阻塞物体碰撞，终止内层循环
                direction?.let {
                    badDirection=direction;
                    blockable=block
                    return@blockTag
                }
            }

            /** 通知运动物体将要发生碰撞的物体和方向*/
            move.notifyCollision(blockable,badDirection);
        }

        /** 检测销毁 */
        views.filter {it is Destoryable}.forEach { destory->
            destory as Destoryable

            if(destory.isDestory()){
                views.remove(destory)
                if(destory is Eagle) gameOver=true  //游戏结束了
                if(destory is EnemyTank) activeEnemyNum--
                if(destory is MyTank) activeMyTankNum--
            }
        }

        /** 检测攻击物体与被攻击物体的碰撞*/
        views.filter { it is Attackable }.forEach forTag@{attack->
            attack as Bullet

            var count=0 //被攻击元素个树

            views.filter {
                when{
                    it !is Sufferable ->false //必须具有接受攻击的能力
                    judgeEnemyTank(attack ,it)->false //不能攻击友方坦克
//                    it ==attack->false //不能与子弹本身碰撞
                    judgeEnemyBullet(attack ,it)->false //不能攻击友方子弹

                    else -> true
                }
            }.forEach { suffer->
                suffer as Sufferable

                var collision=attack.checkCollision(suffer)
                if(collision){
                    attack.notifyAttack(suffer)
                    suffer.notifySuffer(attack)?.let {
                        views.addAll(it)
                    }
                    count++

                    if((suffer !is Wall)and(suffer !is Steel)){ //如果被攻击的不是墙和铁，
                        return@forTag
                    }
                    if(count>=2){ //如果被攻击的元素多余2个(一粒子弹最都同时攻击两个元素)
                        return@forTag
                    }
                }
            }
        }
        /** 检测坦克强化 */
        views.filter { it is Enhanceable }.forEach {
            enhance->enhance as Enhanceable

            views.filter { it is Reinforceable }.forEach forTag@{
                reinforce-> reinforce as Reinforceable

                var isEnhance=enhance.isEnhance(reinforce)
                if(isEnhance){
                    enhance.enhance(reinforce)
                    var type=reinforce.strengthen(enhance)
                    if(type==EnhanceType.TIMING){
                        startTimerTime=currentTime
                    }else if(type==EnhanceType.BLAST){
                        views.filter { it is EnemyTank }.forEach {
                            it as Destructible
                            it.destory()?.let {
                                views.add(it)
                            }
                        }
                    }
                    return@forTag
                }
            }
        }

        /** 敌方坦克自动发射子弹*/
        views.filter{ (it is EnemyTank)and(!gameOver)}.forEach {enemyTank ->
            enemyTank as EnemyTank
            if(currentTime-startTimerTime> timerLength){
                var bullet=enemyTank.shot()
                bullet?.let {
                    views.add(bullet )
                }
            }
        }

        /** 检测敌方坦克存活数量 */
        if((activeEnemyNum<maxActiveEnemyTank)and (bornEnemyNum<totalEnemyNum)
            and (currentTime-lastCheckTime>checkTimeSpace)){

            var max=Math.min(3,maxActiveEnemyTank-activeEnemyNum)
            (1.. max).forEach {
                var x=when(bornEnemyNum%3){
                    0->0
                    1->GameConfig.WINDOW_WIDTH/2-GameConfig.SMALL_BLOCK_WIDTH
                    2->GameConfig.WINDOW_WIDTH-GameConfig.SMALL_BLOCK_WIDTH*2
                    else -> 0
                }
                var EnemyTank=when(Random().nextInt(4)){
                    0->EnemyTank01(x,0)
                    1->EnemyTank02(x,0)
                    2->EnemyTank03(x,0)
                    else->EnemyTank01(x,0)
                }
                views.add(0,EnemyTank)
                bornEnemyNum++
                activeEnemyNum++
            }

            lastCheckTime=currentTime
        }

        /** 检测我方坦克存活数量 */

        if((activeMyTankNum==0)and (bornMyTankNum<totalMyTankNum)){
            mTank= MyTank(GameConfig.BLOCK_WIDTH*4,GameConfig.BLOCK_WIDTH*12)
            views.add(0,mTank)
            bornMyTankNum++
            activeMyTankNum++
        }

        /** 检测游戏结束 */
        if((bornEnemyNum==totalEnemyNum)and (activeEnemyNum==0)){
            gameOver=true
        }
        if((bornMyTankNum==totalMyTankNum)and (activeMyTankNum==0)){
            gameOver=true
        }
    }

    /** 判断是否为友方坦克*/
    fun judgeEnemyTank(tank01 :Attackable,tank02:Sufferable):Boolean{
        tank01 as Bullet

        return when {
            (tank01.ower is MyTank)and(tank02 is MyTank) -> true
            (tank01.ower is EnemyTank)and(tank02 is EnemyTank) -> true
            else -> false
        }
    }

    /** 判断是否为友方坦克*/
    fun judgeEnemyBullet(view01 :Bullet,view02:Sufferable):Boolean{
        if(view02 !is Bullet){
            return false
        }
        return when {
            (view01.ower is MyTank)and(view02.ower is MyTank) -> true
            (view01.ower is EnemyTank)and(view02.ower is EnemyTank) -> true
            else -> false
        }
    }

}

